package com.xl.basic.aop.aspect;

import com.xl.basic.annotation.LoginIgnored;
import com.xl.basic.annotation.LoginValidated;
import com.xl.basic.annotation.RoleIgnored;
import com.xl.basic.annotation.RoleValidated;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.ResultException;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.entity.param.QueryRoleParam;
import com.xl.basic.service.RoleService;
import com.xl.basic.utils.LoginUtils;
import com.xl.dao.domain.XlRole;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author 钟勇
 * Create in 2024/1/23 13:43
 */
@Component
@Aspect
@Order(2)
@RequiredArgsConstructor
public class RoleAspect {

    private final RoleService roleService;

    @Before("execution(* com.xl..*.controller..*.*(..))")
    public void roleValidate(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();

        Method method = ((MethodSignature) signature).getMethod();
        Class<?> declaring = signature.getDeclaringType();

        //方法上有忽略权限的注解，不做后续处理
        RoleIgnored roleIgnored = method.getAnnotation(RoleIgnored.class);
        if (roleIgnored != null) {
            return;
        }

        //获取方法上的权限注解
        RoleValidated methodeRoleValidated = method.getAnnotation(RoleValidated.class);

        //获取类上的权限注解
        RoleValidated classRoleValidated = declaring.getAnnotation(RoleValidated.class);
        //类和方法上都没有权限注解，不做权限控制
        if (methodeRoleValidated == null && classRoleValidated == null) {
            return;
        }

        List<String> roleSignList = new ArrayList<>();
        if (methodeRoleValidated != null) {
            String[] roleNames = methodeRoleValidated.allowRoles();
            if (roleNames != null && roleNames.length > 0) {
                Collections.addAll(roleSignList, roleNames);
            }

        }

        if (classRoleValidated != null) {
            String[] roleNames = classRoleValidated.allowRoles();
            if (roleNames != null && roleNames.length > 0) {
                Collections.addAll(roleSignList, roleNames);
            }
        }

        //对权限名称去重
        if (!roleSignList.isEmpty()) {
            roleSignList = roleSignList.stream().distinct().toList();
        }

        Result<UserInfo> userInfoRes = LoginUtils.getUserInfo();
        if (userInfoRes.isErr()) {
            throw new ResultException(ResultEnums.LoginError.getResult(userInfoRes.getMessage()));
        }
        UserInfo userInfo = userInfoRes.getResult();

        //查询下用户的角色
        Result<List<XlRole>> roleListRes = roleService.queryRoleList(
                new QueryRoleParam().setUserId(userInfo.getUserId())
        );
        if (roleListRes.isErr()) {
            throw new ResultException(ResultEnums.AuthError.getResult(roleListRes.getMessage()));
        }

        List<XlRole> userRoleList = roleListRes.getResult();
        if (userRoleList == null || userRoleList.isEmpty()) {
            throw new ResultException(ResultEnums.AuthError.getResult("用户无访问权限"));
        }

        //不要求权限，只要用户有任何后台角色，都可以访问
        if (roleSignList.isEmpty()) {
            return;
        }

        //找到任何一个角色匹配,就返回有权限
        List<String> finalRoleSignList = roleSignList;
        if (userRoleList.stream().anyMatch(item -> finalRoleSignList.contains(item.getRoleSign()))) {
            return;
        }

        throw new ResultException(ResultEnums.AuthError.getResult("用户无权限访问"));
    }
}
